define(["dojo/dom-construct", "esri/layers/GraphicsLayer",
    this.path + '../4.x/plugins/esri/WaterFlow.js'
], function(DomConstruct, Layer, WaterFlow) {
    let layerClass = Layer.createSubclass({
        declaredClass: 'WaterFlowLayer',
        name: 'waterFlow',
        type: 'waterFlow',
        setData: function(mapView, layer) {
            this.mapView = mapView;
            this.options = layer.layer || {};
            this.data = layer.layer.data || [];
            this.isClear = false;

            this.createCanvas();
            this.createListeners();
            // return this._layerViewCreated(evt);

            if (this.canvas) {
                renderWaterFlow.bind(this)()
            }

            function renderWaterFlow() {
                if (!this.$WaterFlow) {
                    this.render(this.canvas)
                } else if (this.$WaterFlow) {
                    const extent = this.getExtent();
                    this.$WaterFlow.update(this.getData(), extent[0], extent[1], extent[2], extent[3])
                }
            }
        },
        createCanvas: function() {
            if (!this.view) {
                console.log('缺少view!');
            };
            let canvas = DomConstruct.create('canvas', {
                width: this.view.width,
                height: this.view.height,
                style: 'position:absolute;top:0;left:0'
            });
            let parent = this.view.canvas.parentElement;
            parent.appendChild(canvas);
            this.canvas = canvas;
            this.context = canvas.getContext('2d');
        },
        /*添加监听*/
        createListeners: function() {
            var me = this;
            let view = this.view;
            this._watchExtent = view.watch("extent", () => {
                this.visibilityToggle(false);
                this.deBounce(() => {
                    clearTimeout(this.timer);
                    this.visibilityToggle(true);
                }, 800)();
            });
        },
        deBounce: function(fn, delay) {
            return (...args) => {
                if (this.timer) {
                    clearTimeout(this.timer);
                }
                this.timer = setTimeout(() => {
                    fn(...args);
                }, delay)
            }
        },
        showLayer: function() {
            this.visibilityToggle(true);
        },
        hideLayer: function() {
            this.visibilityToggle(false);
        },
        removeLayer: function() {
            if (this.canvas) {
                this.canvas.parentNode.removeChild(this.canvas);
            }
            this._watchExtent.remove();
            this._watchExtent = null;


            if (this.$WaterFlow) this.$WaterFlow.stop()
            delete this.canvas
            delete this.$WaterFlow
            delete this._cloneLayer
            this.inherited(arguments);
        },
        setScale: function(view, _element) {
            var scale = view.scale;

            if (this.options && this.options.minScale && this.options.maxScale) {
                if (scale > this.options.minScale || scale < this.options.maxScale) {
                    _element.style.display = 'none';
                    this._elementVisible = false;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                };
            } else if (this.options && this.options.minScale > 0) {
                if (scale > this.options.minScale) {
                    _element.style.display = 'none';
                    this._elementVisible = false;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                };
            } else if (this.options && this.options.maxScale > 0) {
                if (scale < this.options.maxScale) {
                    _element.style.display = 'none';
                    this._elementVisible = false;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                };
            } else {
                _element.style.display = 'block';
                this._elementVisible = true;
            };
        },
        visibilityToggle: function(visible) {
            if (visible) {
                this.canvas.style.display = 'block';
            } else {
                this.canvas.style.display = 'none';
            }
        },
        render: function() {
            const extent = this.getExtent();
            if (this.canvas && !this.$WaterFlow) {
                this.$WaterFlow = new WaterFlow({
                    canvas: this.canvas,
                    data: this.data,
                    map: this.view,
                    colorStyle: this.options.colorStyle
                });
                this.$WaterFlow.start(extent[0], extent[1], extent[2], extent[3]);
            } else if (this.canvas && this.$WaterFlow) {
                this.$WaterFlow.start(extent[0], extent[1], extent[2], extent[3]);
            }
            this.setScale(this.view, this.canvas);
        },
        getExtent: function() {
            var extent = this.view.geographicExtent || this.view.extent;

            return [
                [
                    [0, 0],
                    [this.view.width, this.view.height]
                ],
                this.view.width,
                this.view.height, [
                    [extent.xmin, extent.ymin],
                    [extent.xmax, extent.ymax]
                ]
            ]
        },
        stop: function() {
            this.$WaterFlow.stop();
        },
        redraw() {
            this.stop();
            if (!this.visible) {
                return;
            }
            this.setScale(this.view, this.canvas);
            if (!this._elementVisible) {
                return
            }
            this._canvas.width = this.map.width;
            this._canvas.height = this.map.height;
            const extent = this.getExtent()
            setTimeout(function() {
                this.$WaterFlow.start(extent[0], extent[1], extent[2], extent[3]);
            });
        },
        getData: function() {
            return this.data;
        }
    });

    return layerClass;
});